<?php
/**
 * Created by PhpStorm.
 * User: papa
 * Date: 18/5/21
 * Time: 14:57
 */

namespace app\api\service;


use app\admin\model\ChargeRule;
use app\admin\model\ShopInfo;
use app\admin\model\YearSurvey;
use app\api\lib\exception\MissException;
use app\api\lib\exception\SuccessMessage;
use app\api\lib\exception\TokenException;
use app\api\model\FacePay;
use app\api\model\Goods;
use app\api\model\Order;
use app\api\model\OrderDetail;
use app\api\model\User;
use app\api\model\UserCharge;
use EasyWeChat\Factory;
use think\Db;
use app\api\model\UserLevel;

class Pay
{
    //获取用户信息
    public function getUser()
    {
        //获取用户uid并生成用户实例
        $uid = TokenService::getCurrentUid();
        if (!$uid) {
            throw new TokenException();
        }
        return User::get($uid);
    }

    //当面付的支付
    public function FacePay($data)
    {
        //获取用户对象
        $user = $this->getUser();
        //检查发送过来的优惠劵和积分是否有效
        OrderService::checkFacePayData($data, $user);
        $openid = $user->openid;
        //实例化微信支付配置
        $payment = $this->wxPayConfig();
        //调用统一下单，获取prepay_id
        $shopInfo = ShopInfo::find();
        $sn = OrderService::makeOrderNo('facepay');
        $result = $payment->order->unify([
            'body' => $shopInfo->name, //商家名称
            'out_trade_no' => $sn,  //订单号
//            'total_fee' => $data['price'] * 100,    //金额
            'total_fee' => 1,
            'trade_type' => 'JSAPI',
            'openid' => $openid,
            'notify_url' => getHostDomain().'/api/v2/pay/notify',
        ]);
        if ($result) {
            //生成当面付的订单
            OrderService::createFaceOrder($data, $sn, $result, $user);
        }
        //获取js支付参数
        $res =  $payment->jssdk->sdkConfig($result['prepay_id']);
        throw new SuccessMessage(['data' => $res]);
    }

    //商品下单
    public function OrderPay($sn)
    {
        $order = \app\admin\model\Order::get(['sn'=>$sn]);
        $user = $this->getUser();
        $openid = $user->openid;
        //实例化微信支付配置
        $payment = $this->wxPayConfig();
        //调用统一下单，获取prepay_id
        $shopInfo = ShopInfo::find();
        $result = $payment->order->unify([
            'body' => $shopInfo->name, //商家名称
            'out_trade_no' => $sn,  //订单号
            'total_fee' => $order->true_price * 100,    //金额
            'trade_type' => 'JSAPI',
            'openid' => $openid,
            'notify_url' => getHostDomain().'/api/v2/pay/notify',
        ]);
        //获取js支付参数
        $res =  $payment->jssdk->sdkConfig($result['prepay_id']);
        throw new SuccessMessage(['data' => $res]);
    }

    //未付款订单重新发起支付
    public function snPay($sn,$type)
    {
        $user = $this->getUser();
        //检测订单
        OrderService::checkSn($sn,$user);
        if($type == 1){
            $this->OrderPay($sn);
        }
        if($type == 2){
            $order = Order::where(['sn'=>$sn])->find();
            $data['sn'] = $sn;
            $data['true_price'] = $order->getData('true_price');
            OrderService::handleAccount($data,$user);
        }
    }

    //付款后异步通知处理
    public function payNotify()
    {
        //实例化支付对象
        $app = $this->wxPayConfig();
        //调用支付结果通知方法
        $response = $app->handlePaidNotify(function ($message, $fail) use($app) {
            // 获取通知里的 "微信支付订单号"
            $sn = $message['out_trade_no'];
            $order = \app\admin\model\Order::get(['sn'=>$sn]);
            if (!$order || $order->status != 1) { // 如果订单不存在 或者 订单已经支付
                return true; // 告诉微信，已经处理，无须在通知
            }
            //再次向微信查询订单，防止三方模拟请求欺诈
            $result = $app->order->queryByOutTradeNumber($sn);
            if($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS' || $result['trade_state'] != 'SUCCESS'){
                return true;    //此处保证必须完成支付,或者返回微信不做处理
            }
            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {

                    OrderService::facePayOrderChange($order);   //处理订单
                    // Points::hanler($order); //处理积分
                    $this->updateUserInfo1($order);
                    //订单关系数据的统计
                    $this->updateCount($order,$sn);
                    $this->goodsSaleNum($sn);

                    // 用户支付失败
                } elseif ($message['result_code'] === 'FAIL') {
                    return true;
                }
            } else {
                return $fail('通信失败，请稍后再通知我');
            }
            return true; // 返回处理完成
        });
        $response->send(); // return $response;
    }
    //修改用户表中用户消费的总金额


    public function updateUserInfo1($order)
    {
        $price = $order->getData('true_price');
        $uid = $order->getData('user_id');
        $oldTotalPayUser = User::field('total_pay')->where(['id'=>$uid])->find();
        $oldTotalPay = $oldTotalPayUser->getData('total_pay');
        $newTotalPay = $oldTotalPay + $price;
        $userLevel = UserLevel::userLevel();
        $level_id = '';
        foreach($userLevel as $k=>$v){
            if(($newTotalPay > $v[0]) && ($newTotalPay < $v[1])){
                $level_id = $k;
            }
        }
        User::where(['id'=>$uid])->update(['total_pay'=>$newTotalPay,'level_id'=>$level_id]);
    }


    public function updateUserInfo($sn)
    {
        $orderss = Order::where('sn','eq',$sn)->find()->toArray();
        $price = $orderss['true_price'];
        $uid = $orderss['user_id'];
//        $price = 388.00;
//        $uid = 35;
        $oldTotalPayUser = User::field('total_pay')->where(['id'=>$uid])->find();
        $oldTotalPay = $oldTotalPayUser->getData('total_pay');
        $newTotalPay = $oldTotalPay + $price;
        $userLevel = UserLevel::userLevel();
        $level_id = '';
        foreach($userLevel as $k=>$v){
            if(($newTotalPay > $v[0]) && ($newTotalPay < $v[1])){
                $level_id = $k;
            }
        }
        User::where(['id'=>$uid])->update(['total_pay'=>$newTotalPay,'level_id'=>$level_id]);
    }

    //对订单数量，订单金额，订单总利润进行统计
    private function updateCount($order,$sn)
    {
        $map = getTodayCount();
        $result = YearSurvey::where($map)->select();
        if(!$result){
            $result = YearSurvey::create($map);
        }
        YearSurvey::where($map)->setInc('order_total_money',$order->price);
        YearSurvey::where($map)->setInc('order_profit_money',$this->getProfit($sn));
        YearSurvey::where($map)->setInc('order_total',1);
    }

    //计算订单总利润
    private function getProfit($sn)
    {
        $order_profit_money = 0;
        //订单包含菜品信息
        $order = FacePay::get(['sn' => $sn]) ?: \app\admin\model\Order::get(['sn'=>$sn]);
        if($order->getTable() == 'order'){
            $orderService = new OrderService();
            //订单菜品详细数据
            $foods = $orderService->getFoodsByOrder($order->detail);
            foreach ($foods as $food) {
                foreach ($order->detail as $detail) {
                    if($food['id'] == $detail['food_id']){
                        $order_profit_money += ($food['sale_price'] - $food['cost_price']) * $detail['count'];
                    }
                }
            }
        }
        return $order_profit_money;
    }

    //对 商品 进行 总销量 的 统计0
    private function goodsSaleNum($sn)
    {
        $order = FacePay::get(['sn' => $sn]) ?: \app\admin\model\Order::with('detail')->where(['sn'=>'20180523710413'])->find();
        if($order->getTable() == 'order'){
            $goods = $order->detail;
            foreach ($goods as $k => $v){
                Goods::where(['id' => $v['food_id']])->setInc($v['count']);
            }
        }
    }

    //退款接口
    public function handleRefund($id)
    {
        $order = FacePay::get($id) ?: \app\admin\model\Order::get($id);
        $user = $this->getUser();
        if($order->user_id != $user->id){
            return new MissException(['msg'=>'非法操作']);
        }
        $orderStatus = [1,5,6];
        if(!$order || in_array($order->status,$orderStatus)) { // 如果订单不存在 或者不允许情形
            return new MissException(['msg'=>'不存在的订单，或者订单异常']);
        }
        $app = $this->wxPayConfig();
        $result = $app->refund->byOutTradeNumber($order->sn,$order->sn,$order->true_price*100, $order->true_price*100, [
            // 可在此处传入其他参数，详细参数见微信支付文档
            'refund_desc' => '退款',
        ]);
        if($result['return_code'] == 'SUCCESS'){
            if($result['result_code'] == 'SUCCESS'){
                return true;
            }
        }else{
            return false;
        }
    }

    //充值得方法
    public function deposit($price)
    {
        //获取用户对象
        $user = $this->getUser();
        $openid = $user->openid;
        //实例化微信支付配置
        $payment = $this->wxPayConfig();
        //调用统一下单，获取prepay_id
        $shopInfo = ShopInfo::find();
        $sn = OrderService::makeOrderNo('deposit');
        $result = $payment->order->unify([
            'body' => $shopInfo->name, //商家名称
            'out_trade_no' => $sn,  //订单号
            'total_fee' => $price * 100,    //金额
//            'total_fee' => 1,
            'trade_type' => 'JSAPI',
            'openid' => $openid,
            'notify_url' => 'https://bj.lbdgkj.com/api/v2/pay/deposit_notify',
//            'notify_url' => 'http://mjdks.gotoip3.com',
        ]);
        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            //获取js支付参数
            $res =  $payment->jssdk->sdkConfig($result['prepay_id']);
            throw new SuccessMessage(['data' => $res]);
        }else{
            throw new MissException(['data' => $result['return_msg']]);
        }

    }

    public function depositNotify()
    {
        //实例化支付对象
        $app = $this->wxPayConfig();
        //调用支付结果通知方法
        $response = $app->handlePaidNotify(function ($message, $fail) use($app) {
            //再次向微信查询订单，防止三方模拟请求欺诈
            $result = $app->order->queryByOutTradeNumber($message['out_trade_no']);
            if($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS' || $result['trade_state'] != 'SUCCESS'){
                return true;    //此处保证必须完成支付,或者返回微信不做处理
            }
            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    //充值后的系列数据修改
                    self::doDepositService($message);
                    // 用户支付失败
                } elseif ($message['result_code'] === 'FAIL') {
                    return true;
                }
            } else {
                return $fail('通信失败，请稍后再通知我');
            }
            return true; // 返回处理完成
        });
        $response->send(); // return $response;

    }

    //充值成功后的系列数据修改处理
    public static function doDepositService($message)
    {
        $user = User::get(['openid'=>$message['openid']]);
        $data['user_id'] = $user->id;
        $data['sn'] = $message['out_trade_no'];
        $data['charge_money'] = $message['total_fee']/100;
        $rule = self::doDepositRule1($data['charge_money']);
        $donate_money = 0;
        if($rule && is_array($rule)){
            $donate_money = $rule['donate_money'];
        }
        $data['donate_money'] = $donate_money;
        $data2['charge_money'] = $data['charge_money'] + $user->getData('charge_money');
        $data2['donate_money'] = $donate_money + $user->getData('donate_money');
        $data2['account_money'] = $user->getData('account_money') + $donate_money + $data['charge_money'];
        Db::startTrans();
        try{
            UserCharge::create($data);
            User::where('id','eq',$user->id)->update($data2);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
        }
    }

//    public static function doDepositService($message)
//    {
//        //获取订单金额，并匹配充值规则，获取是否符合赠送条件
//        $rule = self::doDepositRule($message['total_fee']);
//        $user = User::get(['openid' => $message['openid']]);    //获取用户信息

//        $userCharge = new UserCharge();     //实例化
//        $userCharge->user_id = $user->id;   //用户id
//        $userCharge->sn = $message['out_trade_no']; //商户订单号
//        $userCharge->charge_moeny = $message['total_fee'] / 100;    //支付金额
//        //如果符合赠送条件
//        if($rule) {
//            $ruleResult = ChargeRule::where('charge_money', $rule)->find();
//            $donate_money = $ruleResult->donate_money;
//        }else{
//            $donate_money = 0;
//        }
//        //使用事务
//        Db::startTrans();
//        try{
//            $userCharge->donate_money = $donate_money;
//            //生成并保存订单信息
//            $userCharge->save();
//            //如果符合规则，增增加充值金额
//            $price = $message['total_fee']/100 + $donate_money;
//            User::where('id',$user->id)->inc('account_money',$price )
//                ->inc('charge_money',$message['total_fee']/100)
//                ->inc('donate_money',$donate_money/100)
//                ->update();
//            Db::commit();
//            return true;
//        } catch (\Exception $e) {
//            Db::rollback();
//        }
//    }

    //处理充值规则
    public static function doDepositRule($price)
    {
        //查找所有规则
        $rule = ChargeRule::order('charge_money','ASC')->select();
        $findRue = [];
        foreach($rule as $key=>$value){
            //如果不符合任何一个规则
            if($price < $rule[$key]['charge_money']){
                if($key == 0){
                    return 0;
                }
            }
            //如果匹配到，则返回匹配的第一个
            if($price >= $rule[$key]['charge_money'] && $price < $rule[$key+1]['charge_money']){
                return $rule[$key]['charge_money'];
            }
        }
        return $findRue;
    }


    //处理充值规则
    public static function doDepositRule1($price)
    {
        $rule = ChargeRule::field('charge_money,charge_money_max,donate_money,id')->select();
        foreach($rule as $k=>$v){
            if(($price>=$v->getData('charge_money')) && $price<$v->getData('charge_money_max')){
                $arr['id'] = $v->getData('id');
                $arr['donate_money'] = $v->getData('donate_money');
                return $arr;
            }
        }
        return false;
    }


    //微信支付配置实例化
    private function wxPayConfig()
    {
        $wxConfig = getWxCache();
        if (!$wxConfig['appid'] || !$wxConfig['mchid'] || !$wxConfig['key']) {
            throw new MissException(['msg' => '微信支付参数缺失']);
        }
        $config = [
            'app_id' => $wxConfig['appid'],
            'mch_id' => $wxConfig['mchid'],
            'key' => $wxConfig['key'],
//            'notify_url' => getHostDomain().config('secure.pay_back_url'),
        ];
        return Factory::payment($config);
    }
}